package com.xuanyue.componentauth.token;


import com.alibaba.fastjson2.JSON;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.xuanyue.componentauth.exception.LoginExpiredException;
import com.xuanyue.componentauth.exception.NotFindTokenException;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Calendar;

public class TokenTool{

    private static TokenCfg cfg;
    private static boolean isInit = false;


    /**
     * 初始化
     * @param cfg
     */
    public static void init( TokenCfg cfg ){

        if( cfg == null ){
            throw new RuntimeException("需要向Spring容器注入com.xuanyue.componentauth.token.TokenCfg");
        }

        TokenTool.cfg = cfg;
        boolean isOk = true;

        if( cfg.getExpiresMinute() == null ){
            isOk = false;
        }
        if( cfg.getSecretKey() == null ){
            isOk = false;
        }
        if( cfg.getHeaderName() == null ){
            isOk = false;
        }
        if( !isOk ){
            throw new RuntimeException("TokenTool.init()失败,配置类TokenCfg不允许有缺省值");
        }else{
            TokenTool.isInit = true;
        }

    }

    /**
     * 检查是否初始化
     */
    private static void isInit(){
        if( !isInit ){
            throw new RuntimeException( "使用TokenTool前请先初始化" );
        }
    }


    /**
     * 根据传入的对象生成token
     * @param data
     * @return token串
     */
    public static String createToken( Object data ){

        isInit();

        /* 设置过期时间 */
        Calendar instance = Calendar.getInstance();
        instance.add(Calendar.SECOND, cfg.getExpiresMinute());

        /* 创建令牌 */
        String token = JWT.create()
                // 设置主体json内容
                .withClaim("json", JSON.toJSONString( data ))
                // 设置国企时间
                .withExpiresAt(instance.getTime())
                // 设置签名
                .sign(Algorithm.HMAC256(cfg.getSecretKey()));
        return token;
    }

    /**
     * 解析token
     * 从header中获取
     * @return 权限对象
     */
    public static<T> T parseToken( Class<T> clazz ){

        isInit();

        /* 获取到token */
        HttpServletRequest request = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getRequest();
        String token = request.getHeader( cfg.getHeaderName() );
        if( token == null || token.length() == 0 ){
            throw new NotFindTokenException();
        }

        String json = "";

        try{
            /* 从token中获取token */
            json =  JWT.require(Algorithm.HMAC256( cfg.getSecretKey())).build().verify(token).getClaim("json").asString();
        }catch ( TokenExpiredException e ){
            throw new LoginExpiredException();
        }


        return JSON.parseObject( json, clazz );
    }

    /**
     * 判断当前是否有效登录
     * @return
     */
    public static boolean isLogin(){

        isInit();

        /* 获取到token */
        HttpServletRequest request = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getRequest();
        String token = request.getHeader( cfg.getHeaderName() );

        try{
            JWT.require(Algorithm.HMAC256( cfg.getSecretKey())).build().verify(token);
        }catch ( Exception e ){
            return false;
        }

        return true;
    }

}
